package com.gopay.common.cps.manager.auosettle.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.gopay.common.constants.autosettle.AutoSettleBankDailyStatsConstants;
import com.gopay.common.cps.manager.auosettle.AutoSettleDailyStatsAssembleManager;
import com.gopay.common.cps.manager.holiday.HolidayInfomationUtilManager;
import com.gopay.common.domain.autosettle.AsBankSettleDailyStats;
import com.gopay.common.domain.autosettle.bo.AutoSettleBankDailyStatsBO;
import com.gopay.common.util.CalendarUtils;


/** 
 * @fileName  AutoSettleDailyStatsAssembleManagerImpl.java
 * @author  张建龙 
 * @date 创建时间：2016年1月19日 上午11:51:30
 */
@Service("autoSettleDailyStatsAssembleManager")
public class AutoSettleDailyStatsAssembleManagerImpl implements AutoSettleDailyStatsAssembleManager {
	
	private Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Resource(name="holidayInformationUtilManager")
	private HolidayInfomationUtilManager holidayInfomationManager;

	@Override
    public AutoSettleBankDailyStatsBO assembleAutoSettleBankDailyStatsBOThisWeekExpected(
			AutoSettleBankDailyStatsBO lastWeekActual,Date date)  {
		Assert.notNull(lastWeekActual.getAvgAmt(), "上周实际平均为空");
		Assert.notNull(lastWeekActual.getSumAmt(), "上周实际统计为空");
		Assert.notNull(lastWeekActual.getPeakAmt(), "上周实际峰值为空");
		AutoSettleBankDailyStatsBO thisWeekExpected = new AutoSettleBankDailyStatsBO();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		
		Map<Integer, BigDecimal> expectedMap = getExpectedMap(calendar, lastWeekActual);
		
		thisWeekExpected.setFieldName(AutoSettleBankDailyStatsConstants.FIELD_NAME_THIS_WEEK_EXPECTED_NAME);
		
		thisWeekExpected.setMondayAmt(expectedMap.get(0));
		thisWeekExpected.setTuesdayAmt(expectedMap.get(1));
		thisWeekExpected.setWednesdayAmt(expectedMap.get(2));
		thisWeekExpected.setThursdayAmt(expectedMap.get(3));
		thisWeekExpected.setFridayAmt(expectedMap.get(4));
		thisWeekExpected.setSaturdayAmt(expectedMap.get(5));
		thisWeekExpected.setSundayAmt(expectedMap.get(6));
		
		thisWeekExpected.setSumAmt(expectedMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_SUM_AMT));
		thisWeekExpected.setAvgAmt(expectedMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_AVG_AMT));
		thisWeekExpected.setPeakAmt(expectedMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_PEAK_AMT));
		
		return thisWeekExpected;
	}

	public BigDecimal getExpectdAmtByPeakRule(
			AutoSettleBankDailyStatsBO lastWeekActual) {
		return lastWeekActual.getPeakAmt().multiply(AutoSettleBankDailyStatsConstants.ACTUAL_CACULATE_RULE_PEAK_RATIO);
	}


	private BigDecimal getExpectdAmtByAvgRule(
			AutoSettleBankDailyStatsBO lastWeekActual) {
		return lastWeekActual.getAvgAmt().multiply(AutoSettleBankDailyStatsConstants.ACTUAL_CACULATE_RULE_AVG_RATIO);
	}
	
	private Map<Integer, BigDecimal> getExpectedMap(Calendar calendar,AutoSettleBankDailyStatsBO lastWeekActual) {
		Map<Integer, BigDecimal> expectedMap = new HashMap<Integer, BigDecimal>();
		BigDecimal sumAmt = new BigDecimal("0");
		BigDecimal avgAmt = new BigDecimal("0");
		BigDecimal peakAmt = new BigDecimal("0");
		BigDecimal count = new BigDecimal("0"); //统计本周有多少天是非节假日
		for(int a=0;a<7;a++){
			boolean booleanflag = false;
			booleanflag = holidayInfomationManager.isAutoSettleHoliday(calendar.getTime());
			if(!booleanflag){
				count=count.add(new BigDecimal("1"));
				char flag = translateDateToExpectdRule(calendar);
				if(flag==AutoSettleBankDailyStatsConstants.ACTUAL_CACULATE_RULE_PEAK){
					expectedMap.put(a, getExpectdAmtByPeakRule(lastWeekActual));
				}else if(flag==AutoSettleBankDailyStatsConstants.ACTUAL_CACULATE_RULE_AVG){
					expectedMap.put(a, getExpectdAmtByAvgRule(lastWeekActual));
				}
				if(expectedMap.get(a).compareTo(peakAmt)==1){
					peakAmt = expectedMap.get(a);
				}
				sumAmt = sumAmt.add(expectedMap.get(a));
			}else{
				expectedMap.put(a, null);
			}
			calendar.add(Calendar.DAY_OF_YEAR, 1);
		}
		if(count.compareTo(new BigDecimal("0"))==0){
			
		}else{
			avgAmt = sumAmt.divide(count,2);
		}
		expectedMap.put(7, sumAmt);
		expectedMap.put(8, avgAmt);
		expectedMap.put(9, peakAmt);
		return expectedMap;
	}
	
	private char translateDateToExpectdRule(Calendar calendar){
		switch (calendar.get(Calendar.DAY_OF_WEEK)) {
		case 2:
			return AutoSettleBankDailyStatsConstants.ACTUAL_CACULATE_RULE_PEAK;
		case 3:
			return AutoSettleBankDailyStatsConstants.ACTUAL_CACULATE_RULE_PEAK;
		case 4:
			return AutoSettleBankDailyStatsConstants.ACTUAL_CACULATE_RULE_AVG;
		case 5:
			return AutoSettleBankDailyStatsConstants.ACTUAL_CACULATE_RULE_AVG;
		case 6:
			return AutoSettleBankDailyStatsConstants.ACTUAL_CACULATE_RULE_AVG;
		case 7:
			return AutoSettleBankDailyStatsConstants.ACTUAL_CACULATE_RULE_AVG;
		case 1:
			return AutoSettleBankDailyStatsConstants.ACTUAL_CACULATE_RULE_AVG;
		default:
			return AutoSettleBankDailyStatsConstants.ACTUAL_CACULATE_RULE_AVG;
		}
		
		
	}

	@Override
	public List<AutoSettleBankDailyStatsBO> assembleAutoSettleBankDailyStatsBO(
			List<AsBankSettleDailyStats> asBankSettleDailyStatsList, Date beginDate, Date endDate) {
		List<AutoSettleBankDailyStatsBO> autoSettleBankDailyStatsBOList = new ArrayList<AutoSettleBankDailyStatsBO>();
		Calendar flagCalendar  = Calendar.getInstance();
		flagCalendar.setTime(beginDate);
		flagCalendar.add(Calendar.DAY_OF_YEAR, 7);
		int count = 0;
		for (int i = 0; i < asBankSettleDailyStatsList.size(); i++) {
			Calendar tempCallndar  = Calendar.getInstance();
			tempCallndar.setTime(asBankSettleDailyStatsList.get(i).getSettleDate());
			if(flagCalendar.after(tempCallndar)){
				count++;
			}
		}
		List<AsBankSettleDailyStats> asBankSettleDailyStatsLastWeekActualList = asBankSettleDailyStatsList.subList(0, count);
		List<AsBankSettleDailyStats> asBankSettleDailyStatsThisWeekActualList = asBankSettleDailyStatsList.subList(count, asBankSettleDailyStatsList.size());
		
		AutoSettleBankDailyStatsBO lastWeekActual = assembleAutoSettleBankDailyStatsBOLastWeekActual(asBankSettleDailyStatsLastWeekActualList);
		AutoSettleBankDailyStatsBO thisWeekActual = assembleAutoSettleBankDailyStatsBOThisWeekActual(asBankSettleDailyStatsThisWeekActualList);
		AutoSettleBankDailyStatsBO thisWeekExpected = assembleAutoSettleBankDailyStatsBOThisWeekExpected(lastWeekActual, flagCalendar.getTime());
		
		autoSettleBankDailyStatsBOList.add(lastWeekActual);
		autoSettleBankDailyStatsBOList.add(thisWeekExpected);
		autoSettleBankDailyStatsBOList.add(thisWeekActual);
		
		return autoSettleBankDailyStatsBOList;
	}


	@Override
	public AutoSettleBankDailyStatsBO assembleAutoSettleBankDailyStatsBOLastWeekActual(
			List<AsBankSettleDailyStats> asBankSettleDailyStatsList) {
		AutoSettleBankDailyStatsBO lastWeekActual = new AutoSettleBankDailyStatsBO();
		Map<Integer, BigDecimal> acutalMap = getAcutalMap(asBankSettleDailyStatsList);
		
		lastWeekActual.setFieldName(AutoSettleBankDailyStatsConstants.FIELD_NAME_LAST_WEEK_ACTUAL_NAME);
		
		lastWeekActual.setMondayAmt(acutalMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_MONDAY));
		lastWeekActual.setTuesdayAmt(acutalMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_TUESDAY));
		lastWeekActual.setWednesdayAmt(acutalMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_WEDNESDAY));
		lastWeekActual.setThursdayAmt(acutalMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_THURSDAY));
		lastWeekActual.setFridayAmt(acutalMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_FRIDAY));
		lastWeekActual.setSaturdayAmt(acutalMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_SATURDAY));
		lastWeekActual.setSundayAmt(acutalMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_SUNDAY));
		
		lastWeekActual.setSumAmt(acutalMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_SUM_AMT));
		lastWeekActual.setAvgAmt(acutalMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_AVG_AMT));
		lastWeekActual.setPeakAmt(acutalMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_PEAK_AMT));
		
		return lastWeekActual;
	}
	
	public Map<Integer, BigDecimal> getAcutalMap(List<AsBankSettleDailyStats> asBankSettleDailyStatsList){
		Map<Integer, BigDecimal> acutalMap = new HashMap<Integer, BigDecimal>();
		BigDecimal sumAmt = new BigDecimal("0");
		BigDecimal avgAmt = new BigDecimal("0");
		BigDecimal peakAmt = new BigDecimal("0");
		BigDecimal count = new BigDecimal("0"); //统计本周有多少天是非节假日
		BigDecimal curAmt = null; //当天的金额
		for(int a=0;a<asBankSettleDailyStatsList.size();a++){
				count = count.add(new BigDecimal("1"));
				curAmt = (BigDecimal) asBankSettleDailyStatsList.get(a).getSettleAmt();
				sumAmt = sumAmt.add(curAmt);
				if(curAmt.compareTo(peakAmt)==1){
					peakAmt = curAmt;
				}
				Calendar calendar = Calendar.getInstance();
				calendar.setTime(asBankSettleDailyStatsList.get(a).getSettleDate());
				int weekDay = CalendarUtils.getWeekday(calendar);
				acutalMap.put(weekDay-1, asBankSettleDailyStatsList.get(a).getSettleAmt());
		}
		if(asBankSettleDailyStatsList.size()==0){
			
		}else{
			avgAmt = sumAmt.divide(count,2);
		}
		acutalMap.put(7, sumAmt);
		acutalMap.put(8, avgAmt);
		acutalMap.put(9, peakAmt);
		
		return acutalMap;
	}

	@Override
	public AutoSettleBankDailyStatsBO assembleAutoSettleBankDailyStatsBOThisWeekActual(
			List<AsBankSettleDailyStats> asBankSettleDailyStatsList){
		AutoSettleBankDailyStatsBO thisWeekActual = new AutoSettleBankDailyStatsBO();
		Map<Integer, BigDecimal> acutalMap = getAcutalMap(asBankSettleDailyStatsList);
		
		thisWeekActual.setFieldName(AutoSettleBankDailyStatsConstants.FIELD_NAME_THIS_WEEK_ACTUAL_NAME);
		
		thisWeekActual.setMondayAmt(acutalMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_MONDAY));
		thisWeekActual.setTuesdayAmt(acutalMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_TUESDAY));
		thisWeekActual.setWednesdayAmt(acutalMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_WEDNESDAY));
		thisWeekActual.setThursdayAmt(acutalMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_THURSDAY));
		thisWeekActual.setFridayAmt(acutalMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_FRIDAY));
		thisWeekActual.setSaturdayAmt(acutalMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_SATURDAY));
		thisWeekActual.setSundayAmt(acutalMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_SUNDAY));
		
		thisWeekActual.setSumAmt(acutalMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_SUM_AMT));
		thisWeekActual.setAvgAmt(acutalMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_AVG_AMT));
		thisWeekActual.setPeakAmt(acutalMap.get(AutoSettleBankDailyStatsConstants.Week_DAY_PEAK_AMT));
		
		return thisWeekActual;
	}
}
